package com.pet.interceptor;

import com.pet.constant.JwtClaimsConstant;
import com.pet.context.BaseContext;
import com.pet.properties.JwtProperties;
import com.pet.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    //preHandle方法会在请求处理之前被调用。
    // 它接收三个参数：request（请求对象）、response（响应对象）和handler（处理器对象，通常是HandlerMethod或HandlerMapping的实例）。
    // boolean是一个基本数据类型，用于表示逻辑值，即true或false。
    // boolean类型的变量只能存储这两种值之一。它通常用于条件判断，控制流语句，或者作为某些方法的返回类型。
    public boolean preHandle
            (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("当前线程的id：" + Thread.currentThread().getId());

        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法，直接放行
            return true;
        }
        //放行OPTIONS请求
        String method = request.getMethod();
        if ("OPTION".equals(method)) {
            log.info("放行请求头：{}",method);
            return true;
        }
        if ("OPTIONS".equals(method)) {
            log.info("放行请求头：{}",method);
            return true;
        }

        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            //对token进行校验
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            log.info("jwt校验成功:{}",claims);
            //根据获取claims对管理员和用户进行区分 其中管理端包含empId,用户包含userId，以此作为区分

            //通过调用的接口url进行判断 管理端端调用admin下面的接口 用户调用user下面的接口 //都不匹配进行报错

            String url = request.getRequestURI();
           try {
               //区分用户和管理者 获取到使用者id
               if((url.contains("admin") || url.contains("user")) && claims.get(JwtClaimsConstant.EMP_ID)!=null){
                   BaseContext.setCurrentId(Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString()));
                   log.info("当前用户为管理员");
               }else if (url.contains("user") && claims.get(JwtClaimsConstant.USER_ID)!=null){
                   BaseContext.setCurrentId(Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString()));
                   log.info("当前用户为用户");
               }else{//进行报错
                   response.getWriter().write("Permission error");
                   response.setStatus(401);
                   return false;
               }
           } catch (Exception e) {
               e.printStackTrace();//捕获异常
               log.info("权限错误");
           }
            //3、通过，放行
            return true;
        } catch (Exception ex) {
            //4、不通过，响应401状态码
            response.getWriter().write("token error，please check account and password or log back in");
            response.setStatus(401);
            return false;
        }
    }
}
